/* 
 * File:   OnboardAnalogDigitalConverter.cpp
 * Author: ejordan
 * 
 * Created on May 7, 2013, 11:46 AM
 */
#include "IAnalogDigitalConverter.h"
#include "InternalAnalogDigitalConverter.h"

/*! \brief Initializes a new instance of the Onboard Adc class.
 *
 * Initializes a new instance of the Adc class using the
 * onboard ADC using the specified input channels.
 *
 * Values:\n
 * VRef+: \b referenceVoltage
 * VRef-: Vss\n
 * Accuracy: \b bitResolution
 *
 * @param inputs Analog input pins
 * @param referenceVoltage Positive reference voltage
 * @param bitResolution Bit resolution of ADC
 */
InternalAnalogDigitalConverter::InternalAnalogDigitalConverter(
												   UINT32 inputs,
												   float referenceVoltage,
												   unsigned char bitResolution)
{
	this->_referenceVoltage = referenceVoltage;
	this->_quantizationLevels = (1 << bitResolution);

	CloseADC10();

	SetChanADC10(ADC_CH0_NEG_SAMPLEA_NVREF);
	OpenADC10(
			ADC_FORMAT_INTG |
			ADC_CLK_AUTO |
			ADC_AUTO_SAMPLING_ON,

			ADC_VREF_AVDD_AVSS |
			ADC_OFFSET_CAL_DISABLE |
			ADC_SCAN_ON |
			ADC_SAMPLES_PER_INT_16 |
			ADC_ALT_BUF_OFF |
			ADC_ALT_INPUT_OFF,

			ADC_CONV_CLK_INTERNAL_RC |
			ADC_SAMPLE_TIME_15,

			inputs,

			~inputs
			);

	EnableADC10(); // Enable the ADC

	// Wait for the first sample to come in
	while (!mAD1GetIntFlag())
	{
		asm("nop");
	}

	return;

}

/*! \brief Reads a single value from the Analog-to-Digital (ADC) converter
 *
 * Reads a single value from the Analog-to-Digital (ADC) converter\n
 *
 * @param channel Analog channel to read
 */
float InternalAnalogDigitalConverter::Read(UINT32 channel)
{
	return (ReadADC10(channel) * this->_referenceVoltage) / (float) this->_quantizationLevels;
}

/*! \brief Closes the Adc device and returns pins to their
 * default state.
 */
InternalAnalogDigitalConverter::~InternalAnalogDigitalConverter()
{
	PORTSetPinsDigitalIn(IOPORT_B, 0xFF);
}

/*! \brief Sets the reference voltage for the ADC converstions.
 *
 * Sets the reference voltage for the ADC converstions.
 *
 * @param referenceVoltage Positive reference voltage
 */
void InternalAnalogDigitalConverter::SetReferenceVoltage(float referenceVoltage)
{
	this->_referenceVoltage = referenceVoltage;
}